package net.avcompris.binding.annotation;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static net.avcompris.binding.BindConfiguration.*;
import static net.avcompris.binding.BindConfiguration.DEFAULT_NODES_EMPTY_ATTRIBUTES;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
 * this annotation is to pass configuration parameters to the binding engine. 
 *
 * @author David Andrianavalontsalama
 */
@Documented
@Target(TYPE)
@Retention(RUNTIME)
public @interface Nodes {

	/**
	 * should we see attributes and elements the same? Default is 
	 * <tt>false</tt>, which means we discriminate between attributes and
	 * elements. 
	 * 
	 * <p>
	 * 
	 * Namely, for YAML binders, when 
	 * {@link #elementsEverywhere()}<tt> = false</tt>,
	 * properties with simple values (number, string...) will be bound as
	 * attributes, whereas properties with complex values (map, list...) will
	 * be bound as elements. If {@link #elementsEverywhere()}<tt> = true</tt>,
	 * simple value properties (number, string...) are still seen as attributes,
	 * but are also bound as elements. Not the same XPath expressions will
	 * fit for both cases. 
	 * 
	 * <p>
	 * 
	 * Say for instance we have the following YAML stream:
	 * <blockquote>
	 * <pre>
	 * ajohnson:
	 *   age: 34
	 *   firstName: Andrew
	 *   lastName: Johnson
	 *   items:
	 *     - book: Moby Dick
	 *     - book: Treasure Island
	 *     - dvd: Batman
	 * </pre>
	 * </blockquote>
	 * 
	 * Now the following XPath expressions are equivalent:
	 * <ul>
	 * <li>@XPath("/&#42;/items/&#42;") with @Nodes(elementsEverywhere = true) =&gt; 3 elements
	 * <li>@XPath("/&#42;/items/&#42;") with @Nodes(elementsEverywhere = false) =&gt; 3 elements
	 * <li>@XPath("/&#42;/&#42;/&#42;") with @Nodes(elementsEverywhere = false) =&gt; 3 elements
	 * </ul>
	 * But not:
	 * <ul>
	 * <li>@XPath("/&#42;/&#42;/&#42;") with @Nodes(elementsEverywhere = true) =&gt; 6 elements!
	 * </ul>
	 * The first three examples return <tt>"{book: Moby Dick}",
	 * "{book: Treasure Island}" and "{dvd: Batman}"</tt>, but
	 * the latter returns
	 *  <tt>"34", "Andrew", "Johnson", "{book: Moby Dick}",
	 * "{book: Treasure Island}" and "{dvd: Batman}"</tt>.
	 * 
	 * <p>
	 * 
	 * The {@link #elementsEverywhere()} configuration parameter is not to
	 * be used with DOM binders.
	 */
	boolean elementsEverywhere() default DEFAULT_NODES_ELEMENTS_EVERYWHERE;

	/**
	 * set this to <tt>true</tt> if you want to keep empty attributes in the
	 * DOM-like structure.
	 * Default is <tt>false</tt>, which means empty attributes are deleted
	 * from the in-memory structure. 
	 */
	boolean emptyAttributes() default DEFAULT_NODES_EMPTY_ATTRIBUTES;
	
	/**
	 * set this to <tt>false</tt> if you want to prevent from naming
	 * created DOM elements with YAML maps' keys.
	 * Default is <tt>true</tt>, which means that during the YAML/DOM
	 * conversion, created DOM elements are named from the YAML key. When those
	 * keys contain invalid XML characters, such as whitespaces, it is not
	 * desirable.
	 */
	boolean elementNames() default DEFAULT_NODES_ELEMENT_NAMES;
}
